import { IColor, IPoint } from "@/models/gui";
import { IFn, IFn2 } from "@/models/math";

export function initCanvas (canvas: HTMLCanvasElement) {
  const ctx = canvas.getContext('2d');
  ctx.imageSmoothingEnabled = true;
  ctx.translate(.5, .5);
}

export function clearCanvas (canvas: HTMLCanvasElement) {
  const xMax = canvas.width;
  const yMax = canvas.height;
  const ctx = canvas.getContext('2d');
  ctx.clearRect(0, 0, xMax, yMax);
}

export function drawFn (canvas: HTMLCanvasElement, fn: IFn, color: IColor, clear = false) {
  const xMax = canvas.width;
  const yMax = canvas.height;
  const ctx = canvas.getContext('2d');
  if (clear) {
    ctx.clearRect(0, 0, xMax, yMax);
  }
  ctx.strokeStyle = color;
  ctx.lineWidth = 1;
  let prePoint: IPoint = null;
  ctx.beginPath();
  for (let x = 0; x < xMax; x += 5) {
    const y = fn(x);
    const p = toCanvasPoint(canvas, { x, y });
    if (prePoint) {
      ctx.moveTo(prePoint.x, prePoint.y);
      ctx.lineTo(p.x, p.y);
      ctx.stroke();
    }
    prePoint = p;
  }
}

function toCanvasPoint (canvas: HTMLCanvasElement, point: IPoint): IPoint {
  return {
    x: point.x,
    y: canvas.height - point.y
  };
}

function toMathPoint (canvas: HTMLCanvasElement, point: IPoint): IPoint {
  return {
    x: point.x,
    y: canvas.height - point.y
  }
}

export function onPointClick (canvas: HTMLCanvasElement, fn: (p: IPoint) => void) {
  canvas.onclick = (e) => {
    const x = e.offsetX;
    const y = e.offsetY;
    
    const p = toMathPoint(canvas, { x: x * 2, y: y * 2 });
    fn(p);
  }
}


export function drawPoints (canvas: HTMLCanvasElement, points: IPoint[], color: IColor, clear = false) {
  const xMax = canvas.width;
  const yMax = canvas.height;
  const ctx = canvas.getContext('2d');
  if (clear) {
    ctx.clearRect(0, 0, xMax, yMax);
  }
  
  ctx.fillStyle = color;
  points.forEach(point => {
    const p = toCanvasPoint(canvas, point);
    ctx.fillRect(p.x - 3, p.y - 3, 6, 6);
  });
}

export function drawFn2 (canvas: HTMLCanvasElement, fn2: IFn2, start: number, end: number, step: number, color: IColor, clear = false) {
  const xMax = canvas.width;
  const yMax = canvas.height;
  const ctx = canvas.getContext('2d');
  if (clear) {
    ctx.clearRect(0, 0, xMax, yMax);
  }
  ctx.strokeStyle = color;
  ctx.lineWidth = 1;
  let prePoint: IPoint = null;
  ctx.beginPath();
  for (let t = start; t <= end; t += step) {
    const point = fn2(t);
    const p = toCanvasPoint(canvas, point);
    if (prePoint) {
      ctx.moveTo(prePoint.x, prePoint.y);
      ctx.lineTo(p.x, p.y);
      ctx.stroke();
    }
    prePoint = p;
  }
}
